package com.cloud.job;

import cn.hutool.core.date.DatePattern;
import cn.hutool.json.JSONUtil;
import com.cloud.comm.CommonContext;
import com.cloud.constant.RedisKeyConstants;
import com.cloud.enums.SupportImportMovieEnum;
import com.cloud.factory.ImportMovieFactory;
import com.cloud.pojo.movie.ImportMovie;
import com.cloud.pojo.movie.MovieAttr;
import com.cloud.service.ImportMovieService;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.model.ListObjectsRequest;
import com.qcloud.cos.model.ObjectListing;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.*;

/**
 * @version v1.0
 * @author: TianXiang
 * @description: 缓存视频播放路径JOB, 以便随机播放使用
 * @date: 2020/11/30
 */

@Component
public class CacheMovieFilePathJob {

    private static final Logger LOG = LoggerFactory.getLogger(CacheMovieFilePathJob.class.getName());

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${cos.bucketName}")
    private String bucketName;

    @Autowired
    private COSClient cosClient;

    private final String GREEN_MOVIE_NAME = "green_movie/";
    private final String MOVIE_NAME = "movie/";

    /**
     * 每30分钟拉取redis里的下载地址进行下载操作
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    public void downloadMovieFromRedis() {
        CommonContext context = CommonContext.getContext();
        context.setMoviesPath("/usr/local/app/docker/nginx/data/html/movies");
        context.setFfmpegExePath("ffmpeg");
        // 日期目录每批只下载50个视频
        String dateDir = context.getMoviesPath() + File.separator + DatePattern.PURE_DATE_FORMAT.format(new Date());
        File dateFile = new File(dateDir);
        if(!dateFile.exists()) {
            dateFile.mkdirs();
        }
        File[] dateDirFiles = dateFile.listFiles();
        if(dateDirFiles.length < 100) {
            String downloadLinkKey = "use";
            List<Map<String, String>> downloadObjList = new ArrayList<>();
            for(int i = 0; i < 100; i++) {
                String value = redisTemplate.opsForList().rightPop(downloadLinkKey);
                if(StringUtils.isBlank(value)) break;
                downloadObjList.add(JSONUtil.toBean(value, Map.class));
            }
            // 去重变量
            Set<String> set = new HashSet<>();
            ImportMovieService importMovieService = ImportMovieFactory.getStrategyService(SupportImportMovieEnum.URL.getCode());
            downloadObjList.stream().forEach(item -> {
                String title = item.get("title");
                if(!set.contains(title)) {
                    // 下载视频
                    String url = item.get("url");
                    ImportMovie importMovie = new ImportMovie().setDownloadFromUrl(url).setSupportFlag(SupportImportMovieEnum.URL.getCode());
                    importMovie.setMovieName(title);

                    importMovieService.importMovie(importMovie, null, rabbitTemplate,redisTemplate);
                }
                set.add(title);
            });
        }
    }

    /**
     * 每天凌晨同步
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void execute() {
        redisTemplate.delete(RedisKeyConstants.MOVIE_LIST_KEY);
        redisTemplate.delete(RedisKeyConstants.GREEN_MOVIE_LIST_KEY);
        LOG.info("定时任务执行: 视频路径同步到缓存");
        List<MovieAttr> movieAttrList = new ArrayList<>(), greenMovieAttrList = new ArrayList<>();

        ListObjectsRequest objectRequest = new ListObjectsRequest();
        // 设置bucket名称
        objectRequest.setBucketName(bucketName);
        // prefix表示列出的object的key以prefix开始
        objectRequest.setPrefix(this.MOVIE_NAME);
        // 当前目录的对象, 不含下级
        objectRequest.setDelimiter("/");
        // 设置最大遍历出多少个对象, 一次listobject最大支持1000
        objectRequest.setMaxKeys(1000);

        List<String> movieFirstDirPathList = cosClient.listObjects(objectRequest).getCommonPrefixes();
        this.getMovieInfo(movieAttrList, movieFirstDirPathList);

        objectRequest.setPrefix(this.GREEN_MOVIE_NAME);
        List<String> greenMovieFirstDirPathList = cosClient.listObjects(objectRequest).getCommonPrefixes();
        this.getMovieInfo(greenMovieAttrList, greenMovieFirstDirPathList);

//        LOG.info("movieAttrList : {}  greenMovieAttrList: {}", movieAttrList, greenMovieAttrList);
        // 记入到redis-list数据结构
        ListOperations<String, String> redisList = redisTemplate.opsForList();
        List<String> listJson = new ArrayList<>();
        for (MovieAttr movieAttr : movieAttrList) {
            listJson.add(JSONUtil.toJsonStr(movieAttr));
        }
        redisList.rightPushAll(RedisKeyConstants.MOVIE_LIST_KEY,listJson);
        listJson.clear();
        for (MovieAttr movieAttr : greenMovieAttrList) {
            listJson.add(JSONUtil.toJsonStr(movieAttr));
        }
        redisList.rightPushAll(RedisKeyConstants.GREEN_MOVIE_LIST_KEY,listJson);
        LOG.info("定时任务完成");
    }

    private void getMovieInfo(List<MovieAttr> movieAttrList, List<String> movieFirstDirPathList) {
        for (String firstDirPath : movieFirstDirPathList) {
            ListObjectsRequest firstDirPathObjectsRequest = new ListObjectsRequest();
            firstDirPathObjectsRequest.setBucketName(bucketName);
            firstDirPathObjectsRequest.setPrefix(firstDirPath);
            firstDirPathObjectsRequest.setDelimiter("/");
            firstDirPathObjectsRequest.setMaxKeys(1000);
            ObjectListing firstDirPathObjectListing = cosClient.listObjects(firstDirPathObjectsRequest);
            List<String> secondDirPathList = firstDirPathObjectListing.getCommonPrefixes();
            for (String secondDirPath : secondDirPathList) {
                // 有可能ts的个数超出了一次响应的最大对象数
                ObjectListing secondDirPathObjectListing;
                ListObjectsRequest secondDirPathObjectsRequest = new ListObjectsRequest();
                secondDirPathObjectsRequest.setBucketName(bucketName);
                secondDirPathObjectsRequest.setPrefix(secondDirPath);
                secondDirPathObjectsRequest.setDelimiter("/");
                secondDirPathObjectsRequest.setMaxKeys(1000);
                int count = 1;// 超出翻页阀值100结束
                do {
                    secondDirPathObjectListing = cosClient.listObjects(secondDirPathObjectsRequest);
                    // 列出的object列表
                    String moviePath = secondDirPathObjectListing.getObjectSummaries().stream().filter(item -> -1 != item.getKey().indexOf(".m3u8")).map(COSObjectSummary::getKey).findFirst().orElse(null);
                    if(null == moviePath) { // 设置当前数据的节点名称  操作下一页
                        secondDirPathObjectsRequest.setMarker(secondDirPathObjectListing.getNextMarker());
                    }else {
                        String dateDirName = moviePath.split("/")[1];
                        String dirName = moviePath.split("/")[2];
                        String movieName = moviePath.split("/")[3];
                        movieAttrList.add(new MovieAttr().setDateDirName(dateDirName).setDirName(dirName).setMovieName(movieName));
                    }
                    count++;
                    if(count == 100) {
                        break;
                    }
                }while (secondDirPathObjectListing.isTruncated());
            }
        }
    }

}
